/**
 *******************************************************************************
 * @FileName  : bb.h
 * @Author    : GaoQiu
 * @CreateDate: 2020-02-18
 * @Copyright : Copyright(C) GaoQiu
 *              All Rights Reserved.
 *******************************************************************************
 *
 * The information contained herein is confidential and proprietary property of
 * GaoQiu and is available under the terms of Commercial License Agreement
 * between GaoQiu and the licensee in separate contract or the terms described
 * here-in.
 *
 * This heading MUST NOT be removed from this file.
 *
 * Licensees are granted free, non-transferable use of the information in this
 * file under Mutual Non-Disclosure Agreement. NO WARRENTY of ANY KIND is provided.
 *
 *******************************************************************************
 */

#ifndef BB_H_
#define BB_H_

#include "bb_api.h"

#include "utils/track.h"
#include "utils/assert.h"
#include "utils/byte_stream.h"
#include "utils/bd_addr.h"
#include "utils/utils.h"

#include "stack/rf/rf_phy.h"

typedef void (*BB_DebugResetCback_t)(void);

typedef struct{
	BB_DebugResetCback_t           BBDebugResetCback;
	BB_32KTrackingStartCback_t     BB_32KTrackingStartCback;
	BB_Get32KTrackingValueCback_t  BB_Get32KTrackingValueCback;

	uint32_t                       cur32kRCRateHz;
	uint32_t                       cur32kTrack;
	uint32_t                       historyTrack[6];
	uint32_t                       rcl32kTrackStartTick;

	uint8_t                        sleepClockSrc;   /*! sleep clock source. 0:32K RC, 1: 32k XTL.*/
	uint8_t                        curPwrMode;
	uint8_t                        cur32kTrackFlag; /*!< 32k clock track flag. 1:track start, 0:track value get*/
    uint8_t                        dtmState;
}BBCb_t;

extern BBCb_t bbCb;

typedef struct{
	int8_t   connTxSettle1M;
	int8_t   connTxSettle2M;
	int8_t   connTxSettleCoded;

	int8_t   advTxSettle1M;
	int8_t   advTxSettle2M;
	int8_t   advTxSettleCoded;

	int8_t   scanTxSettle1M;
	int8_t   scanTxSettle2M;
	int8_t   scanTxSettleCoded;

	int8_t   advRxSettle;
	int8_t   scanRxSettle;
	int8_t   connRxSettle;

	int8_t   RFU[4];
}TxRxSettleInfo_t;

#ifdef IP_108
extern const TxRxSettleInfo_t txRxSettle;
	/*! [Panchip] TX/RX Settle. AA_match delay = 10us => Rx tolrent = 40 + 10 + 4 = 54us*/
	//PHY SPI = 32M/2
	#define BB_ADV_TX_RX_SETTLE      3
	#define BB_SCAN_TX_RX_SETTLE     1
	#define BB_MST_TX_RX_SETTLE      1
	#define BB_SLV_TX_RX_SETTLE      1

	#define BB_ADV_RX_SETTLE         6
	#define BB_SCAN_RX_SETTLE        10
	#define BB_RX_SETTLE             10

	#define BB_PRE_TX_RX_MAX_TIME    60 //us
#elif defined(IP_107)
extern TxRxSettleInfo_t txRxSettle;
	/*! [Panchip] TX/RX Settle. AA_match delay = 17us => Rx tolrent = 40 + 17 + 5 = 62us*/
	//PHY SPI = 32M/2
	#define BB_ADV_TX_RX_SETTLE      9
	#define BB_SCAN_TX_RX_SETTLE     8
	#define BB_MST_TX_RX_SETTLE      8
	#define BB_SLV_TX_RX_SETTLE      8

	#define BB_ADV_RX_SETTLE         8
	#define BB_SCAN_RX_SETTLE        10
	#define BB_RX_SETTLE             10

	#define BB_PRE_TX_RX_MAX_TIME    60 //us
#endif

/*! BB clock control */
#define BB_CLK_ENABLE()          CLK->AHB_CLK_CTRL |= BIT(6)|BIT(7)
#define BB_CLK_DISABLE()         CLK->AHB_CLK_CTRL &= ~(BIT(6)|BIT(7))

/*! Get RSSI form packet. */
#define BB_RSSI(pPkt)                       (*(int32_t *)( (uint32_t)pPkt + ((pPkt[1] + 4 + 3) & ~3) )) //(*(int32_t *)( (uint32_t)pPkt + 4 * ((pPkt[1] + 4 + 3)>>2) ))
#define BB_CONN_RSSI(pPkt, enc)             (*(int32_t *)( (uint32_t)pPkt + ((pPkt[1] + 4 + (enc)*4 + 3) & ~3) ))

/*! */
#define BB_JITTER_USECS                     (bbCb.sleepClockSrc ? (80):(500))
#define BB_INT_DELAY_US                     (40)
#define BB_UNCODED_FSM_SETUP_TIME_US        (270)
#define BB_CODED_FSM_SETUP_TIME_US          (500)

#define BB_TICK_TO_US_32768(t)              ( 30 * (t) + ( (((t) << 8) + ((t) << 3) + (t)) >> 9 ) )

#define BB_32K_RC_MEASURE_CNT               16
#if BB_32K_RC_MEASURE_CNT == 32
	/* !!!Note:max 4s */
	#define BB_TICK_TO_US_32K_RC(t)         (((t) * bbCb.cur32kTrack) >> 10)
	#define BB_US_TO_TICK_32K_RC(us)        (( (us)<<10 ) / bbCb.cur32kTrack)
#else //16
    /* !!!Note:max 8s */
	#define BB_TICK_TO_US_32K_RC(t)         (((t) * bbCb.cur32kTrack) >> 9)
	#define BB_US_TO_TICK_32K_RC(us)        (( (us)<<9 ) / bbCb.cur32kTrack)
#endif

#if 1
	/*! 32KHz */
	#define BB_US_TO_TICK(us)    BB_UsToTick(us)
	//#define BB_US_TO_TICK2(us)   (bbCb.sleepClockSrc ? (( ((us) * 512  + 7812) / 15625 )) : BB_US_TO_TICK(us))
	#define BB_US_TO_TICK2(us)   BB_UsToTick(us)
	#define BB_TICK_TO_US(t)     BB_TickToUs(t)
#else
	/*! 32.768KHz */
	#define BB_US_TO_TICK(us)    BB_UsToTick(us)
	#define BB_US_TO_TICK2(us)   (( ((us) * 512  + 7812) / 15625 ))
	#define BB_TICK_TO_US(t)     BB_TickToUs(t)
#endif

#define BB_MS_TO_TICK(ms)        BB_US_TO_TICK(ms * 1000)


/*!  BaseBand packet head length. */
#define BB_PKT_HDR_LEN           4
#define BB_PKT_HDR_LL_LEN_Pos    1 /*!< XXX:[Panchip] backup LL payload Length field posiztion. */
#define BB_LL_PKT_HDR_LEN        4 /*!< XXX:[Panchip] */


/*! PHY types. HCI evt*/
enum{
  BB_PHY_NONE                   = 0,            /*!< PHY not selected. */
  BB_PHY_LE_1M                  = 1,            /*!< LE 1M PHY. */
  BB_PHY_LE_2M                  = 2,            /*!< LE 2M PHY. */
  BB_PHY_LE_CODED               = 3,            /*!< LE Coded PHY. */
  BB_PHY_MAX                    = BB_PHY_LE_CODED,
};

enum{
	BB_PHY_OPTIONS_NONE         = 0,
	BB_PHY_OPTIONS_S2_PREFERRED = 1,
	BB_PHY_OPTIONS_S8_PREFERRED = 2,
};

enum{
	BB_DTM_NONE = 0,
	BB_DTM_RX   = 1,
	BB_DTM_TX   = 2,
};

/*! BB BLE IT define */
#define BB_BLE_IT_CMD_DONE               BIT(3) /*!< FSM Cmd done */
#define BB_BLE_IT_UPD_REQ                BIT(2) /*!< FSM Update Request */
#define BB_BLE_IT_CS_DONE                BIT(1) /*!< channel select */
#define BB_BLE_IT_LST_DONE               BIT(0) /*!< white-list/resolving-list/black-list done */

/*! BB BLE IT Flag define */
#define BB_BLE_IT_Flag_LST_DONE          BIT(0)
#define BB_BLE_IT_Flag_CS_DONE           BIT(1)
#define BB_BLE_IT_Flag_UPD_REQ           BIT(2)
#define BB_BLE_IT_Flag_CMD_DONE          BIT(3)
#define BB_BLE_IT_Flag_RX_PDU_TYPE_ERR   BIT(4)
#define BB_BLE_IT_Flag_SRC_ADDR_NOT_LST  BIT(5)
#define BB_BLE_IT_Flag_DST_ADDR_ERR      BIT(6)
#define BB_BLE_IT_Flag_CRC_ERR           BIT(7) /*!< RX CRC error */
#define BB_BLE_IT_Flag_RX_TIMEOUT        BIT(8) /*!< RX Timeout */


/*! BB Timer IT define */
#define BB_TIMER_IT_CMP                  BIT(5)
#define BB_TIMER_IT_CMP_ERR              BIT(8)

/*! BB Timer IT Flag define */
#define BB_TIMER_IT_Flag_CMP             BIT(3)
#define BB_TIMER_IT_Flag_CMP_ERR         BIT(9)

/*! BB Timer IT Clear define */
#define BB_TIMER_IT_Clr_CMP              BIT(4)
#define BB_TIMER_IT_Clr_CMP_ERR          BIT(7)
#define BB_TIMER_IT_Clr_ALL              (BIT(7)|BIT(4))


/* LL power mode */
#define BB_PWR_MODE_DEEP_SLEEP       0  /*!< Disable module power for deep sleep */
#define BB_PWR_MODE_SLEEP            1  /*!< Disable module power for sleep */
#define BB_PWR_MODE_LL               2  /*!< only Enable LL module power */
#define BB_PWR_MODE_SEC              3  /*!< only Enable Secure module power */
#define BB_PWR_MODE_LL_SEC           4  /*!< only Enable LL and Secure module power */
#define BB_PWR_MODE_MAC              5  /*!< only Enable MAC module power */
#define BB_PWR_MODE_LL_MAC           6  /*!< only Enable LL and MAC module power */
#define BB_PWR_MODE_LL_MAC_SEC       7  /*!< only Enable LL/MAC/Secure module power */


/*! BB BLE FSM mode */
#define BB_FSM_MODE_CONNECTABLE_ADV          0
#define BB_FSM_MODE_CONNECTABLE_DIRECT_ADV   1
#define BB_FSM_MODE_NON_CONN_ADV             2
#define BB_FSM_MODE_SCAN_UNDIRECT_ADV        3
#define BB_FSM_MODE_ACTIVE_SCAN              4
#define BB_FSM_MODE_PASSIVE_SCAN             5
#define BB_FSM_MODE_INITIATOR                6
#define BB_FSM_MODE_MASTER_CONN              7
#define BB_FSM_MODE_SLAVE_CONN               8
#define BB_FSM_MODE_DTM_TRANSMITTER          9
#define BB_FSM_MODE_DTM_RECEIVER             10
#define BB_FSM_MODE_DTM_CONTINUE             11
#define BB_FSM_MODE_DTM_STOP                 12
#define BB_FSM_MODE_AUX_ADV                  13
#define BB_FSM_MODE_PASSIVE_INITIATOR        14
#define BB_FSM_MODE_AUX_CHAIN                15


/*! BB BLE List mode */
#define BB_LIST_MODE_NONE                     0
#define BB_LIST_MODE_WHITELIST                1  /*!< for common */
#define BB_LIST_MODE_SCAN_LIST                2  /*!< Filter LL_SCAN_REQ for adv */
#define BB_LIST_MODE_CONN_LIST                3  /*!< Filter LL_CONN_IND for adv */
#define BB_LIST_MODE_EXT_SCAN_LIST            4  /*!< for scan */
#define BB_LIST_MODE_INIT_LIST                5  /*!< for initiator */
#define BB_LIST_MODE_EXT_SCAN_NO_LIST         6  /*!< for scan */

void BB_Init(uint8_t clk32kXtlEn);
void BB_Reset(void);
void BB_ResetCommon(void);

void BB_SetBlePhy(uint8_t rxPhy, uint8_t txPhy, uint8_t phyOpt);
void BB_SetBleChannel(uint8_t bleChn);

void BB_SetMaxMoreDataNum(uint8_t md);
uint32_t BB_GetDataNumPerConn(void);
void BB_SetRxBuf(uint8_t id, uint8_t *pbuf, uint32_t len);
void BB_SetTxBuf(uint8_t id, uint8_t *pbuf, uint32_t len);

void BB_SetPwrMode(uint8_t pwrMode);
void BB_SetPwrModeEx(uint8_t pwrMode, uint8_t stateCheckEn);

static _inline_ uint32_t BB_GetPwrMode(void)
{
	return ((BB_REG32(BB_CTRL_ADDR) & BB_CTRL_PM_PWR_STATE_Mask)>>BB_CTRL_PM_PWR_STATE_Pos);
}

uint32_t BB_UsToTick(uint32_t us);
uint32_t BB_TickToUs(uint32_t t);

//BLE IRQ API
static _inline_ void BB_EnableBleIrq(uint32_t BB_BLE_IT)
{
	BB_REG32(BB_BLE_INT_MASK_ADDR) &= ~BB_BLE_IT;
}

static _inline_ void BB_DisableBleIrq(uint32_t BB_BLE_IT)
{
	BB_REG32(BB_BLE_INT_MASK_ADDR) |= BB_BLE_IT; //Write 1 disable
}

static _inline_ void BB_ClearBleITFlag(uint32_t BB_BLE_IT)
{
	BB_REG32(BB_BLE_INT_CLR_ADDR) |= BB_BLE_IT;
	BB_REG32(BB_BLE_INT_CLR_ADDR) &= ~BB_BLE_IT;
}

static _inline_ uint16_t BB_GetBleITFlag(void)
{
	return BB_REG32(BB_BLE_INT_STAT_ADDR);
}

//BLE BB API
static _inline_ void BB_SetAccessCode(uint32_t AA)
{
	BB_REG32(BB_PP2_ADDR) = AA;
}

static _inline_ void BB_SetCrcInit(uint32_t crcInit)
{
	BB_REG32(BB_PP3_ADDR) = crcInit & BB_PP3_CRC_INIT_Mask;
}

static _inline_ void BB_SetTxSettleTime(int8_t us)
{
	//uint32_t txSettle = us;
	uint32_t txSettle = RF_GetTxSettleTime() + us;
	BB_REG_WRITE(BB_FSM2_ADDR, BB_FSM2_PHY_TX_CFG_Mask, BB_FSM2_PHY_TX_CFG_Pos, txSettle);
}

static _inline_ void BB_SetRxSettleTime(int8_t us)
{
	//uint32_t rxSettle = us;
	uint32_t rxSettle = RF_GetRxSettleTime() + us;
	BB_REG_WRITE(BB_FSM4_ADDR, BB_FSM4_PHY_RX_CFG_Mask, BB_FSM4_PHY_RX_CFG_Pos, rxSettle);
}

static _inline_ void BB_SetMaxRxLength(uint8_t maxRxLen)
{
	BB_REG_WRITE(BB_PP1_ADDR, BB_PP1_MAX_RX_LEN_Mask, BB_PP1_MAX_RX_LEN_Pos, maxRxLen);
}

static _inline_ uint8_t BB_GetPwrModeState(void)
{
	uint32_t pwrMode = BB_REG32(BB_CTRL_ADDR) & BB_CTRL_PM_PWR_STATE_Mask;
	pwrMode >>= BB_CTRL_PM_PWR_STATE_Pos;
	return (uint8_t)pwrMode;
}


/**
 * @brief : Start BB FSM
 * @param : fsmMode    can be BB_FSM_MODE_MASTER_CONN/BB_FSM_MODE_SLAVE_CONN...
 * @return: none.
 */
static _inline_ void BB_StartFsm(uint8_t fsmMode)
{
	/* Enable FSM */
	BB_REG_WRITE(BB_FSM1_ADDR, BB_FSM1_FSM_MODE_Mask, BB_FSM1_FSM_MODE_Pos, fsmMode);
}

/**
 * @brief : Disable scan FSM (for scan and initiator)
 * @return: none.
 */
static _inline_ void BB_DisableScanFsm(void)
{
	//Disable FSM
	BB_REG_WRITE(BB_FSM5_ADDR, BB_FSM5_FSM_STOP_Mask, BB_FSM5_FSM_STOP_Pos, 1);
}

/**
 * @brief : Enable scan FSM (for scan and initiator)
 * @return: none.
 */
static _inline_ void BB_EnableScanFsm(void)
{
	//Enable FSM
	BB_REG_WRITE(BB_FSM5_ADDR, BB_FSM5_FSM_STOP_Mask, BB_FSM5_FSM_STOP_Pos, 0);
}

static _inline_ void BB_SetScanMode(uint8_t goonEn)
{
#ifdef IP_108
	BB_REG_WRITE(BB_AOA_RECOGNIZE0_ADDR, BB_SCAN_MD_SCAN_GO_ON_EN_Mask, BB_SCAN_MD_SCAN_GO_ON_EN_Pos, goonEn);

#elif defined(IP_107)
	BB_REG_WRITE(BB_SCAN_MORE_DATA_ADDR, BB_SCAN_MD_SCAN_GO_ON_EN_Mask, BB_SCAN_MD_SCAN_GO_ON_EN_Pos, goonEn);
#endif
}

// unit:us
static _inline_ uint32_t BB_GetTimestamp(void)
{
	return BB_REG32(BB_ACTTMR7_CMP_ADDR);
}

static _inline_ void BB_SetSnAndNesn(uint8_t sn, uint8_t nesn)
{
	uint32_t snNesn = (sn << BB_FSM1_TX_SN_Pos) | (nesn << BB_FSM1_TX_NESN_Pos);

	uint32_t v = BB_REG32(BB_FSM1_ADDR);
	v &= ~(BB_FSM1_TX_SN_Mask | BB_FSM1_TX_NESN_Mask);
	v |= (snNesn & (BB_FSM1_TX_SN_Mask | BB_FSM1_TX_NESN_Mask));
	BB_REG32(BB_FSM1_ADDR) = v;
}

static _inline_ uint8_t BB_GetSn(void)
{
	return (BB_REG32(BB_FSM1_ADDR)>>BB_FSM1_RX_SN_Pos) & 0x01;
}

static _inline_ uint8_t BB_GetNesn(void)
{
	return (BB_REG32(BB_FSM1_ADDR)>>BB_FSM1_RX_NESN_Pos) & 0x01;
}

static _inline_ void BB_SetFirstRxTimeout(uint32_t us)
{
	BB_REG32(BB_FSM9_ADDR) = us;
}

static _inline_ void BB_SetPauseNesnEnable(uint8_t en)
{
	BB_REG_WRITE(BB_FSM12_ADDR, BB_FSM12_PAUSE_NESN_UPD_Mask, BB_FSM12_PAUSE_NESN_UPD_Pos, en);
}

static _inline_ void BB_SetRxTimeout(uint16_t us)
{
	BB_REG32(BB_FSM11_ADDR) = (us & BB_FSM11_RX_TIMEOUT_Mask);
}

static _inline_ uint32_t BB_GetRxPacketNum(void)
{
	uint32_t rxCnt = BB_REG32(BB_FSM1_ADDR) & BB_FSM1_RX_PKT_NUM_Mask;
	return (rxCnt >> BB_FSM1_RX_PKT_NUM_Pos);
}

static _inline_ uint32_t BB_GetTxPacketNum(void)
{
	uint32_t txCnt = BB_REG32(BB_FSM1_ADDR) & BB_FSM1_TX_PKT_NUM_Mask;
	return (txCnt >> BB_FSM1_TX_PKT_NUM_Pos);
}

static _inline_ bool_t BB_IsCrcOK(void)
{
	return (BB_REG32(BB_BLE_INT_STAT_ADDR) & BB_BLE_IT_Flag_CRC_ERR) ? 0:1;
}

static _inline_ bool_t BB_IsRxTimeout(void)
{
	return (BB_REG32(BB_BLE_INT_STAT_ADDR) & BB_BLE_IT_Flag_RX_TIMEOUT) ? 1:0;
}

static _inline_ bool_t BB_IsRxPduTypeErr(void)
{
	return (BB_REG32(BB_BLE_INT_STAT_ADDR) & BB_BLE_IT_Flag_RX_PDU_TYPE_ERR) ? 1:0;
}

/*! BB Timer API (32KHz) */
static _inline_ void BB_SetTimerCmpEventEnable(uint8_t en);
static _inline_ void BB_SetTimerCmpEnable(uint8_t en);
void BB_Delay(uint32_t tick);

static _inline_ void BB_SetTimerEnable(uint8_t en)
{
	BB_REG_WRITE(BB_SLEEP_TIMER1_ADDR, BB_SLEEP_TIMER1_EN_Mask, BB_SLEEP_TIMER1_EN_Pos, en);

	/* Enable Sleep Timer. [!!! important] */
	//BB_Delay(1);//wait 32k sleep timer stable. ???
	sleep_us(60);//wait 32k sleep timer stable. must
}

static _inline_ bool_t BB_IsTimerEnabled(void)
{
	return (BB_REG32(BB_SLEEP_TIMER1_ADDR) & BB_SLEEP_TIMER1_EN_Mask) ? 1:0;
}

static _inline_ void BB_SetTimerEventCmp(uint32_t cmp)
{
	BB_SetTimerCmpEventEnable(0);

	BB_REG32(BB_SLEEP_TIMER2_ADDR) = cmp;

	/* Enable Compare Event Function */
	//BB_REG_WRITE(BB_SLEEP_TIMER1_ADDR, BB_SLEEP_TIMER1_CMP_EVENT_EN_Mask, BB_SLEEP_TIMER1_CMP_EVENT_EN_Pos, 1);
	BB_SetTimerCmpEventEnable(1);
}

static _inline_ void BB_SetTimerEventCmpFine(uint32_t us)
{
	BB_REG32(BB_ACTTMR6_START_CMP_ADDR) = 0;
}

static _inline_ void BB_SetTimerCmp(uint32_t cmp)
{
	BB_SetTimerCmpEnable(0);

	BB_REG32(BB_SLEEP_TIMER4_ADDR) = cmp;

	/* Enable Compare Function */
	//BB_REG_WRITE(BB_SLEEP_TIMER1_ADDR, BB_SLEEP_TIMER1_CMP_EN_Mask, BB_SLEEP_TIMER1_CMP_EN_Pos, 1);
	BB_SetTimerCmpEnable(1);
}

static _inline_ uint32_t BB_GetTimerCmp(void)
{
	return BB_REG32(BB_SLEEP_TIMER4_ADDR);
}

static _inline_ void BB_SetTimerCmpEventEnable(uint8_t en)
{
	BB_REG_WRITE(BB_SLEEP_TIMER1_ADDR, BB_SLEEP_TIMER1_CMP_EVENT_EN_Mask, BB_SLEEP_TIMER1_CMP_EVENT_EN_Pos, en);
}

static _inline_ void BB_SetTimerCmpEnable(uint8_t en)
{
	BB_REG_WRITE(BB_SLEEP_TIMER1_ADDR, BB_SLEEP_TIMER1_CMP_EN_Mask, BB_SLEEP_TIMER1_CMP_EN_Pos, en);
}

//BB_TIMER_IT_CMP
static _inline_ void BB_EnableTimerIrq(uint32_t BB_TIMER_IT)
{
	// 0:enable IRQ; 1:disable IRQ
	BB_REG32(BB_SLEEP_TIMER1_ADDR) &= ~BB_TIMER_IT;
}

static _inline_ void BB_DisableTimerIrq(uint32_t BB_TIMER_IT)
{
	// 0:enable IRQ; 1:disable IRQ
	BB_REG32(BB_SLEEP_TIMER1_ADDR) |= BB_TIMER_IT;
}

static _inline_ uint32_t BB_GetTimerIrqFlag(void)
{
	return BB_REG32(BB_SLEEP_TIMER1_ADDR);
}

static _inline_ void BB_ClearTimerIrqFlag(uint32_t BB_TIMER_IT_Clr)
{
	BB_REG32(BB_SLEEP_TIMER1_ADDR) |= BB_TIMER_IT_Clr;
	BB_REG32(BB_SLEEP_TIMER1_ADDR) &= ~BB_TIMER_IT_Clr;
}

static _inline_ void BB_ClearTimerCmpFineFlag(void)
{
	BB_REG32(BB_INT_STAT_CLR_ADDR) |= BB_INT_STAT_CLR_TIMER_CMP_START_EVT_Mask;
	BB_REG32(BB_INT_STAT_CLR_ADDR) &= ~BB_INT_STAT_CLR_TIMER_CMP_START_EVT_Mask;
}

/*! BB ADV API */
static _inline_ void BB_AdvSetLocalAddr(uint8_t addrType, uint8_t addr[6])
{
	uint32_t addrHi = (uint32_t)(addrType << BB_PP4_ADV_TX_ADDR_TYPE_Pos) | ((addr[5]<<8) | addr[4]);
	BB_REG32(BB_PP4_ADDR) = addrHi;

	uint32_t addrLo = 0;
	BSTREAM_TO_UINT32(addrLo, addr);
	BB_REG32(BB_PP5_ADDR) = addrLo;
}

//user for DIRECT ADV
static _inline_ void BB_AdvSetPeerAddr(uint8_t addrType, uint8_t addr[6])
{
	UNUSED(addrType);

	uint32_t addrHi = ((addr[5]<<8) | addr[4]);
	BB_REG32(BB_PP6_ADDR) = addrHi;

	uint32_t addrLo = 0;
	BSTREAM_TO_UINT32(addrLo, addr);
	BB_REG32(BB_PP7_ADDR) = addrLo;
}

static _inline_ void BB_AdvSetAdvChnMap(uint8_t chnMap)
{
	BB_REG_WRITE(BB_FSM1_ADDR, BB_FSM1_ADV_CHN_MAP_Mask, BB_FSM1_ADV_CHN_MAP_Pos, chnMap);
}

static _inline_ void BB_AdvSetChainPktInterval(uint16_t intervalUs)
{
	BB_REG_WRITE(BB_FSM8_ADDR, BB_FSM8_AUX_CHAIN_PKT_INTERVAL_Mask, BB_FSM8_AUX_CHAIN_PKT_INTERVAL_Pos, intervalUs);
}

/*! BB Init API */
static _inline_ void BB_InitSetPeerAddr(uint8_t addrType, uint8_t addr[6])
{
	uint32_t addrHi = (uint32_t)(addrType << BB_LST4_INITATOR_SYNC_ADDR_TYPE_Pos) | ((addr[5]<<8) | addr[4]);
	BB_REG32(BB_LST4_ADDR) = addrHi;

	uint32_t addrLo = 0;
	BSTREAM_TO_UINT32(addrLo, addr);
	BB_REG32(BB_LST5_ADDR) = addrLo;
}

/*! BB Secure API */
static _inline_ void BB_SecStart(uint8_t pktMask)
{
	                   //AD Len = 1B, MIC = 4B,             SEC_Mode = CCM, SEC_EN =1
	uint32_t secMode = (1ul<<19) | (1ul<<17) | ((pktMask & 0x7F)<<3) | (3ul<<1) | (1ul << 0);
	BB_REG32(BB_SEC_CTRL_ADDR) = secMode;

	BB_REG32(BB_LL_EN_ADDR) |= BIT(0); //Enable LL
}

static _inline_ void BB_SecStop(void)
{
	//BB_REG32(BB_SEC_CTRL_ADDR) &= ~(1ul << 0);
	BB_REG32(BB_SEC_CTRL_ADDR) = 0;
}

static _inline_ uint8_t BB_SecGetMICState(void)
{
	//MIC state is mask bit
	return (uint8_t)((BB_REG32(BB_SEC_CTRL_ADDR) >> 10) & 0x7F);
}

static _inline_ void BB_SecSetIV(uint8_t IV[8])
{
	uint8_t *p = IV;
	uint32_t ivLo = 0;
	uint32_t ivHi = 0;

	BSTREAM_TO_UINT32(ivLo, p);
	BSTREAM_TO_UINT32(ivHi, p);

	BB_REG32(BB_SEC_IV_LO_ADDR) = ivLo;
	BB_REG32(BB_SEC_IV_HI_ADDR) = ivHi;
}

static _inline_ void BB_SecSetKeyAddr(uint8_t id,  uint8_t *pKey)
{
	uint32_t offset = (uint32_t)pKey - BB_BASE;

#if 0
	BB_REG_WRITE(BB_SEC_KEY0_BUF_ADDR, BB_SEC_KEY0_BUF_ADDR_Mask, BB_SEC_KEY0_BUF_ADDR_Pos, offset);
#else
	if(id == 6){
		BB_REG_WRITE(BB_SEC_KEY3_BUF_ADDR, BB_SEC_KEY6_BUF_ADDR_Mask, BB_SEC_KEY6_BUF_ADDR_Pos, offset);
		return;
	}
	// key0-key5
	uint8_t regId = (id >> 1);
	uint32_t KeyAddr = (BB_SEC_KEY0_BUF_ADDR + (regId<<2));
	uint32_t pos = (id % 2) << 4;

	BB_REG_WRITE(KeyAddr, (0xFFFFul << pos), pos, offset);
#endif
}

static _inline_ void BB_SecSetMDLength(uint8_t len)
{
	BB_REG_WRITE(BB_SEC_KEY3_BUF_ADDR, (0x7Ful << 24), 24, len&0x7F);
}

static _inline_ void BB_SecSetTxPktCounter(uint8_t mst, uint32_t pktCnt)
{
	BB_REG_WRITE(BB_SEC_TX_PKT_CNT1_ADDR, (0xFFul << 0), 0, mst);
	BB_REG32(BB_SEC_TX_PKT_CNT2_ADDR) = pktCnt;
}

static _inline_ void BB_SecSetRxPktCounter(uint8_t mst, uint32_t pktCnt)
{
	BB_REG_WRITE(BB_SEC_RX_PKT_CNT1_ADDR, (0xFFul << 0), 0, mst);
	BB_REG32(BB_SEC_RX_PKT_CNT2_ADDR) = pktCnt;
}


static _inline_ void BB_EnableSecIrq(void)
{
	BB_REG32(BB_INT_MASK_ADDR) &= ~BB_INT_MSK_SEC_DONE_Mask;
}

static _inline_ void BB_DisableSecIrq(void)
{
	BB_REG32(BB_INT_MASK_ADDR) |= BB_INT_MSK_SEC_DONE_Mask;
}

static _inline_ void BB_ClearSecIrqFlag(void)
{
	BB_REG32(BB_INT_STAT_CLR_ADDR) |= BB_INT_STAT_CLR_SEC_DONE_Mask;
	BB_REG32(BB_INT_STAT_CLR_ADDR) &= ~BB_INT_STAT_CLR_SEC_DONE_Mask;
}

/*! BB WhiteList API */
void BB_ListInit(void);
void BB_SetListMap(uint32_t curAddr, uint8_t en);

static _inline_ void BB_SetWhiteListMemAddr(uint32_t addr)
{
	uint32_t offset = addr - BB_LIST_RAM_BASE;
	BB_REG_WRITE(BB_LST1_ADDR, (0x7Ful << 3), 3, offset);
}

static _inline_ void BB_SetScanDupMemAddr(uint32_t addr)
{
	uint32_t offset = addr - BB_LIST_RAM_BASE;
	BB_REG_WRITE(BB_LST1_ADDR, (0x7Ful << 17), 17, offset);
}

static _inline_ void BB_SetResolvingListMemAddr(uint32_t addr)
{
	uint32_t offset = addr - BB_LIST_RAM_BASE;
	BB_REG_WRITE(BB_LST1_ADDR, (0x7Ful << 24), 24, offset);
}

static _inline_ void BB_SetFilterPolicy(uint8_t BB_ListMode)
{
	BB_REG_WRITE(BB_LST2_ADDR, BB_LST2_FILT_POLICY_Mask, BB_LST2_FILT_POLICY_Pos, BB_ListMode);
}

/*! BB Resolving List API */


/*! BB Random module API */
void BB_RandInit(void);

static _inline_ uint32_t BB_GetRand(void)
{
	return BB_REG32(BB_RNG2_ADDR);
}

/*! DTM API*/
void BB_DtmStartTransimitterV1(uint8_t txChn, uint8_t dataLen, uint8_t pktType);
void BB_DtmStartTransimitterV2(uint8_t txChn, uint8_t dataLen, uint8_t pktType, uint8_t phy);

void BB_DtmStartReceiverV1(uint8_t rxChn);
void BB_DtmStartReceiverV2(uint8_t rxChn, uint8_t phy, uint8_t moduleId);
uint32_t BB_DtmGetRxPktCnt(void);
uint16_t BB_DtmStop(void);

#endif /* BB_H_ */
